#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author: jixin
# @Date:   2016-03-10 13:30:50
# @Last Modified by:   anchen
# @Last Modified time: 2016-03-10 16:40:03
import SocketServer
import socket

class ChatServer(SocketServer.ThreadingTCPServer):
    def __init__(self,server_address,RequestHandlerClass):
        SocketServer.ThreadingTCPServer.__init__(self,server_address,RequestHandlerClass)
        self.users={}

class ChatRequestHandler(SocketServer.StreamRequestHandler):
    def handle(self):
        self.nickname = None
        flag = True
        while flag:
            self.wfile.write("Please input your nickname\n")
            nick = self.rfile.readline().strip().decode("utf-8")
            flag = self.nickCommand(nick)
        while not flag:
            try:
                rq = self.rfile.readline().strip().decode("utf-8")
                flag = self.parseMsg(rq)
            except socket.error:
                flag = True

    def parseMsg(self,str):
        cmd,arg=None,None
        if str and str[0]=='/':
            if len(str)<2:
                self.wfile.write("input no command\n")
            rqdata=str[1:].split(' ',1)
            if len(rqdata)==2:
                cmd,arg=rqdata
            else:
                cmd=rqdata[0]
            cmdMethod=getattr(self,cmd+"Command",None)
            if not cmdMethod:
                self.wfile.write("error command\n")
                return False
            else:
                return cmdMethod(arg)
        else:
            self.saytoall('<%s> %s\n' % (self.nickname,str))
            return False

    def saytoall(self,msg,includeself=True):
        if msg and msg[-1]!='\n':
            msg+='\r\n'
        for user,sock in self.server.users.items():
            if includeself or user!=self.nickname:
                sock.write(msg.encode('utf-8'))

    def quitCommand(self,str):
        if str:
            self.saytoall('<%s> %s\n' % (self.nickname,str))
        return True

    def allusersCommand(self,str):
        self.wfile.write(','.join(self.server.users.keys())+'\n')
        return False

    def touserCommand(self,str):
        if str:
            strdata=str.split(' ',1)
            if len(strdata)==2:
                usr,msg=strdata
                if msg and msg[-1]!='\n':
                    msg+='\r\n'
                for user,sock in self.server.users.items():
                    if user==usr:
                        sock.write(msg.encode('utf-8'))
                        break
            else:
                self.wfile.write("args's num error!\n")
        return False

    def nickCommand(self,str):
        if not str:
            self.wfile.write("Please input your nickname\n")
            return True
        elif str==self.nickname:
            self.wfile.write("You're already named %s\n" %str)
            return True
        elif self.server.users.get(str,None):
            self.wfile.write("name:%s is already be named here!\n" % str)
            return True
        else:
            if self.nickname:
                oldNickname=self.nickname
                del(self.server.users[self.nickname])
                self.saytoall("%s changed name as %s" % (oldNickname,str))
            
            self.nickname=str
            self.server.users[str]=self.wfile
            self.wfile.write("Welcome:%s\n" % str)
            return False

    def finish(self):
        if self.nickname:
            msg='%s has quit!' % self.nickname
            self.saytoall(msg,False)

            if self.server.users.get(self.nickname):
                del(self.server.users[self.nickname])
        self.request.close()

if __name__ == '__main__':
    Host=''
    Port=9999
    services = ChatServer((Host,Port),ChatRequestHandler)
    services.serve_forever()